#include <stdio.h>

#include "stm32f4xx_hal.h"
#include "w25qxx.h"
#include "stm32_hal_legacy.h"

#define UPDATA_FALG_ADDR    0x200400
#define APP_BIN_LEN_ADDR    0x200402
#define W25Q_FLASHBIN_ADDR  0x100441

#define APP_START_ADDR     0x08010000

void writeFlash_1K(uint32_t addr, uint8_t *data)
{
    uint32_t data_temp;

    HAL_FLASH_Unlock();
    for (uint16_t i = 0; i < 256; i++)
    {
        data_temp = (((data[4 * i + 3] << 24) & 0xff000000) | ((data[4 * i + 2] << 16) & 0xff0000) | ((data[4 * i + 1] << 8) & 0xff00) | ((data[4 * i + 0] << 0) & 0xff));
        if (HAL_FLASH_Program(TYPEPROGRAM_WORD, addr, data_temp) != HAL_OK)
        {
            printf("write flash fail\r\n");
        }
        addr += 4;
    }
    HAL_FLASH_Lock();
}

void upgrade()
{
    uint8_t i_updata_flag[2] = {0};
    int bin_len;
    uint16_t i, temp;
    static uint8_t rData[1024];

    while (1)
    {
        printf("befor check...\r\n");
        /* USER CODE END WHILE */
        W25QXX_Read(i_updata_flag, UPDATA_FALG_ADDR, 0x02);
        printf("i_updata_flag[0] %02x\r\n", i_updata_flag[0]);
        printf("i_updata_flag[1] %02x\r\n", i_updata_flag[1]);
        // 判断是否需要升级
        if (i_updata_flag[0] == 0x77)
        {
            W25QXX_Read((uint8_t*)&bin_len, APP_BIN_LEN_ADDR, 0x04);

            printf("start erase flash...\r\n");
            // HAL_Delay(5000);
            HAL_FLASH_Unlock();
            __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
            // 擦除FLASH
            FLASH_EraseInitTypeDef f;
            f.TypeErase = TYPEERASE_SECTORS;
            f.Sector = 4;
            f.NbSectors = 11;
            f.VoltageRange = FLASH_VOLTAGE_RANGE_3;
            uint32_t PageError = 0;
            // 调用擦除函数
            if (HAL_FLASHEx_Erase(&f, &PageError) != HAL_OK)
            {
                printf("end erase fail\r\n");
            }
            HAL_FLASH_Lock();
            printf("end erase flash\r\n");
            // HAL_Delay(5000);
            temp = bin_len / 1024 + 1;
            printf("start copy W25 data to flash, temp = %d\r\n", temp);

            for (i = 0; i < temp; i++)
            {
                W25QXX_Read(rData, W25Q_FLASHBIN_ADDR + i * 1024, 1024);
                writeFlash_1K(APP_START_ADDR + i * 1024, rData);
            }
            printf("end copy W25 data to flash\r\n");
			int erase_bin_flag = 0x00;
			W25QXX_Write((uint8_t *)&erase_bin_flag,UPDATA_FALG_ADDR,0x02);
            break;
        }
        else
        {
            // HAL_SPI_MspDeInit(&hspi5);
            printf("Upgrade flag is false\r\n");
            break;
        }
    }
}